package com.naiterui.common.repository.config;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.lang.NonNull;

/**
 * 多MongoTemplateConfig配置
 *
 * @author 王泽浩
 * @date 2018/5/22 下午3:56
 * @since 1.0.0
 */
public class MultiMongoTemplateConfiguration implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(MultiMongoTemplateConfiguration.class);

    private Environment environment;

    @Override
    public void postProcessBeanDefinitionRegistry(@NonNull BeanDefinitionRegistry beanDefinitionRegistry)
        throws BeansException {
        // 获取配置
        List<MultiMongoProperties.MongoProperties> mongoPropertiesList =
            this.bindConfigurationProperties(beanDefinitionRegistry);
        mongoPropertiesList.forEach(properties -> {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(MongoTemplate.class);
            // 设置属性
            beanDefinitionBuilder.addConstructorArgValue(new SimpleMongoClientDatabaseFactory(properties.getUri()));
            String beanName = properties.getBeanName();
            AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
            LOGGER.debug("register bean definition [{}] for bean '{}' ", beanDefinition, beanName);
        });
    }

    @Override
    public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public void setEnvironment(@NonNull Environment environment) {
        this.environment = environment;
    }

    /**
     * 获取多mongo配置
     *
     * @param beanDefinitionRegistry
     *
     * @return
     */
    private List<MultiMongoProperties.MongoProperties>
        bindConfigurationProperties(BeanDefinitionRegistry beanDefinitionRegistry) {
        MultiMongoProperties multiMongoProperties =
            ((DefaultListableBeanFactory)beanDefinitionRegistry).getBean(MultiMongoProperties.class);
        ConfigurationProperties annotation =
            AnnotationUtils.findAnnotation(multiMongoProperties.getClass(), ConfigurationProperties.class);
        if (annotation == null) {
            return new ArrayList<>();
        }
        String prefix = annotation.prefix();
        Binder binder = Binder.get(this.environment);
        BindResult<MultiMongoProperties> naiterui = binder.bind(prefix, MultiMongoProperties.class);
        if (naiterui.isBound()) {
            return naiterui.get().getMongo();
        } else {
            return new ArrayList<>();
        }
    }
}
